<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/9/15
 * Time: 0:10
 */

namespace app\index\controller;


use app\index\model\Address;
use app\index\model\BySale;
use app\index\model\Order;
use app\index\model\OrderProduct;
use app\index\model\ProductInfo;
use app\index\model\User as UserModel;
use app\index\model\Product as ProductModel;
use app\lib\exception\DatabaseException;
use think\cache\driver\Redis;
use think\Db;

class WeChat
{
    // 认证微信
    public function Authentication()
    {
        if (!isset($_GET['code'])) {
            $baseUrl = urlencode('http://' . $_SERVER['HTTP_HOST'] . '/cart');
            $url = config('wechat.AuthUrl') . 'connect/oauth2/authorize?appid=' . config('wechat.AppId') . '&redirect_uri=' . $baseUrl . '&response_type=code&scope=snsapi_base&state=123#wechat_redirect';
            header('Location:' . $url);
            exit;
        } else {
            //获取code码，以获取openid
            $code = $_GET['code'];
            $wx_array = $this->getOpenId($code);
            return $wx_array;
        }
    }


    public function getUserInfo()
    {

    }

    // 认证微信
    public function ToMyself()
    {
        if (!isset($_GET['code'])) {
            $baseUrl = urlencode('http://' . $_SERVER['HTTP_HOST'] . '/myself');
            $url = config('wechat.AuthUrl') . 'connect/oauth2/authorize?appid=' . config('wechat.AppId') . '&redirect_uri=' . $baseUrl . '&response_type=code&scope=snsapi_base&state=123#wechat_redirect';
            header('Location:' . $url);
            exit;
        } else {
            //获取code码，以获取openid
            $code = $_GET['code'];
            $wx_array = $this->getOpenId($code);
            return $wx_array;
        }
    }

    // 认证微信
    public function CodeReg()
    {
        if (!isset($_GET['code'])) {
            $baseUrl = urlencode('http://' . $_SERVER['HTTP_HOST'] . '/code_reg');
            $url = config('wechat.AuthUrl') . 'connect/oauth2/authorize?appid=' . config('wechat.AppId') . '&redirect_uri=' . $baseUrl . '&response_type=code&scope=snsapi_base&state=123#wechat_redirect';
            header('Location:' . $url);
            exit;
        } else {
            //获取code码，以获取openid
            $code = $_GET['code'];
            $wx_array = $this->getOpenId($code);
            return $wx_array;
        }
    }

    public function getOpenId($code)
    {
        $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . config('wechat.AppId') . '&secret=' . config('wechat.AppSecret') . '&code=' . $code . '&grant_type=authorization_code';
        $res = $this->http_curl($url);
        // 获取到了 openid
        // 可以通过openid 去拉去微信支付
//        $openid = $res['openid'];
        return $res;
    }

    public function getOpenidFromMp($code)
    {
        $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . config('wechat.AppId') . '&secret=' . config('wechat.AppSecret') . '&code=' . $code . '&grant_type=authorization_code';
        $res = $this->http_curl($url);
        // 获取到了 openid
        // 可以通过openid 去拉去微信支付
        $openid = $res['openid'];
        return $openid;
    }

    public function is_pay()
    {
        $coupon = json_decode(input('post.coupon'));
        $address_id = input('post.address_id');
        $user_id = session('Auth.Uid');
        $username = session('Auth.Username');
        $express = input('post.express');
        // 收货地址信息管理
        $address_info = Address::where('status', 1)
            ->where('id', $address_id)
            ->find();
        if (!$address_info) {
            return setMsg(0, '您的收获地址不合法');
        }
        // 账号合法性
        $user_info = UserModel::where('status', '=', 1)
            ->where('id', $user_id)
            ->find();
        if (!$user_info) {
            return setMsg(0, '您的账号被封禁或者不存在');
        }
        $openid = $user_info->openid;
        $new_cart = new cart();
        $redis = new Redis();
        $key = $username . ':' . 'sAdd';
        $cart_all = [];
        // 先根据集合拿到商品ID
        $idArr = $redis->sMembers($key);
        // 没有商品 空购物车的页面
        if (!$idArr) {
            return redirect('/myself/un_pay');
        }
        $select_idArr = []; // 选中的id
        for ($i = 0; $i < count($idArr); $i++) {
            $k = $username . ':' . $idArr[$i];
            $is_select = $redis->hGet($k, 'select');
            if ($is_select) {
                $cart_all[$idArr[$i]] = $redis->hGetAll($k);
                $select_idArr[] = $idArr[$i];
            }
        }
        $product_info = ProductInfo::where('id', 'in', $select_idArr)
            ->select();
        $count_price = 0; // 总价格
        $all_num = 0; // 商品总数量(选中)
        $distribution_price = 0; // 分成价格 VIP 转1块 非 vip赚一块
        $is_vip = $user_info->is_vip; // 是否是 vip
        $order_product = []; // order_product 表的数据
        // 商品的 product_id_array
        $product_id_array = [];
        foreach ($product_info as $key => $value) {
            $id = $value->id;

            $product_id_array[] = $value->product_id;

            if (($value->status == 0) || ($value->stock == 0)) {
                // 商品下架直接删除此商品
                $new_cart->delCartProduct($id);
            } else if ($value->stock < $cart_all[$id]['num']) {
                // 库存量 < 购买量则强行讲 购买量减为 库存量
                $redis->hset($key, 'num', $value->stock);
                $cart_all[$id]['num'] = $value->stock;
            }
            $all_num += (int)$cart_all[$id]['num'];
            $member_price = $value->member_price;
            $price = $value->price;
            // order_product
            $order_product[$key]['product_id'] = $id;
            $order_product[$key]['num'] = $cart_all[$id]['num'];
//            $order_product[$key]['name'] = $cart_all[$id]['name'];
            $order_product[$key]['color'] = $cart_all[$id]['color'];
            $order_product[$key]['size'] = $cart_all[$id]['size'];
//            $cart_all[$id]['price'] = $price; // 商品单价(P)
//            $cart_all[$id]['member_price'] = $member_price; // 商品单价(V)
            if ($is_vip) {
                $order_product[$key]['is_vip'] = 1;
                $order_product[$key]['price'] = $member_price;
                $distribution_price += 1 * $cart_all[$id]['num'] * 100;
                $count_price += $member_price * 100 * $cart_all[$id]['num'];
            } else {
                $order_product[$key]['price'] = $price;
                $distribution_price += 10 * $cart_all[$id]['num'] * 100;
                $count_price += $price * 100 * $cart_all[$id]['num'];
            }
        }
        // 快递费用 express
        // 验证快递是否是包邮(是否含有优惠)
        $product_id_array = array_unique($product_id_array);
        // 查看是否有优惠
        $sale_exists = ProductModel::with(['productInfo' => function ($query) use ($select_idArr) {
            $query->where('id', 'in', $select_idArr);
        }])
            ->where('id', 'in', $product_id_array)
            ->where('sale_id', '>', 0)
            ->select();
        if ($express == 'free') {
            if ($sale_exists) {
                // 包邮
                $express = [
                    'express_name'  => 'FREE',
                    'express_price' => 0,
                ];
            } else {
                return setMsg(0, '您选择的优惠发生了错误 请您联系在线管理员');
            }
        } else {
            $express = $this->express($address_info->province, $express);
        }
        $order_no = billno();
        try {
            // order 表数据
            $prep_order = [
                'order_no'           => $order_no,
                'user_id'            => session('Auth.Uid'),
                'total_price'        => $count_price / 100,
                'real_price'         => $count_price / 100,
                'snap_img'           => $cart_all[$select_idArr[0]]['url'],
//                'snap_name' => 'name' . '等',
                'snap_name'          => $product_info[0]->name . '等',
                'total_count'        => $all_num,
                'status'             => 1,
                'snap_items'         => json_encode($cart_all),
                'snap_address'       => json_encode($address_info->toArray()),
                'distribution_price' => $distribution_price / 100,
                'express_name'       => $express['express_name'],
                'express_price'      => $express['express_price']
            ];
            Db::startTrans();
            $order_id = Order::insertGetId($prep_order);
            foreach ($order_product as $key => $value) {
                $order_product[$key]['order_id'] = $order_id;
            }
            $order_product_res = OrderProduct::insertAll($order_product);
            if (!$order_product_res) {
                Db::rollback();
                return setMsg(0, '生成订单失败');
            } else {
                if ($sale_exists) {
                    $buy_sale_info = [];
                    $uid = session('Auth.Uid');
                    foreach ($sale_exists as $key => $value) {
                        foreach ($value->product_info as $k => $v) {
                            $buy_sale = [
                                'uid'             => $uid,
                                'sale_id'         => $value->id,
                                'product_id'      => $v->product_id,
                                'product_info_id' => $v->id,
                                'num'             => $redis->hget($username . ':' . $v->id, 'num'),
                                'billno'          => $order_no,
                                'is_pay'          => 0
                            ];
                            array_push($buy_sale_info, $buy_sale);
                        }
                    }
                    $sale_all = BySale::insertAll($buy_sale_info, true);
                    if (!$sale_all) {
                        Db::rollback();
                        return setMsg(0, '生成优惠列表失败');
                    }
                }
                Db::commit();
                // 生成了订单 清除购物车数据购物车的数据 $select_idArr
                // 去掉 集合里的商品 id
                // 去掉
                foreach ($select_idArr as $key => $value) {
                    $redis_product_info = $redis->hget($username . ':' . $value, 'num');
                    // 减去总数量
                    $count_result = $redis->incrBy($username . ':counts', '-' . $redis_product_info);
                    // 为 0 时就删除这一条数据
                    if ($count_result <= 0) {
                        $redis->del($username . ':counts');
                    }
                    // 删除此单品的数据
                    $redis->del($username . ':' . $value);
                    // 移除集合中的单品 id
                    $s_key = $username . ':' . 'sAdd';
                    $del_s_product = $redis->sRem($s_key, $value);
                    // 删除这个数据
                    if ($del_s_product === '') {
                        $redis->del($username . ':sAdd');
                    }
                }
            }
        } catch (Exception $e) {
            throw new DatabaseException([
                'errorCode' => '',
                'msg'       => $e->getMessage()
            ]);
        }
        $pay = new Pay();
        // 最终的付款为总的额度加上 快递费用
        $fina_price = ($count_price + $express['express_price'] * 100) / 100;
        $fina_price = $fina_price - 100 * count($coupon);
        $result = $pay->getPreOrder($openid, $fina_price, $order_no);
        return $result;
    }

    public function http_curl($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($ch);
        curl_close($ch);
        return json_decode($output, true);
    }

    public function call()
    {
        //通知频率为15/15/30/180/1800/1800/1800/1800/3600，单位：秒
        // 如果成功处理，我们返回微信成功处理的信息。否则，我们需要返回没有成功处理。
        //特点：post；xml格式；不会携带参数
        $notify = new WxNotify();
        $notify->Handle();
    }

    public function member_call()
    {
        //通知频率为15/15/30/180/1800/1800/1800/1800/3600，单位：秒
        // 如果成功处理，我们返回微信成功处理的信息。否则，我们需要返回没有成功处理。
        //特点：post；xml格式；不会携带参数
        $notify = new WxNotifyMember();
        $notify->Handle();
    }

    public function express($province, $express)
    {
        // 江浙沪 非江浙沪
        $address_array = ['上海', '江苏', '浙江'];
        if (in_array($province, $address_array)) {
            $address = 'JZH';
        } else {
            $address = 'NO';
        }
        $express_result = config("express.$express")[$address];
        return [
            'express_name'  => $express . '-' . $address,
            'express_price' => $express_result,
        ];
    }

    public function pay()
    {

        $coupon = count(json_decode(input('post.coupon'), true)) ? json_decode(input('post.coupon'), true) : '';
        $address = (int)input('post.address_id') ? (int)input('post.address_id') : 0;
        $uid = (int)session('Auth.Uid') ? (int)session('Auth.Uid') : 0;
        $expressName = (int)input('post.express') ? (int)input('post.express') : 0;
        $goodsList = count(json_decode(input('post.goodslist'), true)) ? json_decode(input('post.goodslist'), true) : '';
//        $goodsList = '[{"pid":"298","gid":"136","num":"2"},{"pid":"299","gid":"138","num":"1"}]';
//        $goodsList = json_decode($goodsList, true);
        if ($address && $uid && $expressName && $goodsList) {
            $checkUser = $this->_checkUser($uid, $address);
            if (!is_array($checkUser)) {
                return json_encode($checkUser);
            }
            $orderInfo = $this->_checkOrder($goodsList, $uid);
            if (!$orderInfo && !is_array($orderInfo)) {
                return json_encode('订单有误, 请刷新或稍后再试');
            } elseif ($orderInfo && !is_array($orderInfo)) {
                $orderInfo = $this->_checkGoods($goodsList, $checkUser);
            }
            $couponState = $this->_checkCoupon($coupon, $uid);
            if (!is_array($couponState)) {
                return json_encode($coupon);
            }
            $express = self::_checkExpress($expressName, $checkUser['province']);
            if (!is_array($express)) {
                return json_encode($express);
            }
            self::_setOrder($orderInfo, $uid, $couponState, $express, $address);

           $result = (new Pay())->getPreOrder($checkUser['userInfo']['openid'], ($orderInfo['order']['deal_price'] * 100 - $couponState['couponPrice'] * 100 + $express['express_price'] * 100) / 100, $orderInfo['order']['order_num'], 'call');
            // $result = (new Pay())->getPreOrder($checkUser['userInfo']['openid'], 0.01, $orderInfo['order']['order_num'], 'call');
            return $result;
        } else {
            return '参数错误';
        }
    }

    /**
     * @var 检查快递
     */
    static private function _checkExpress($expressName, $address)
    {
        // dump($expressName);
        // dump(111111);
        // dump($address);
        if ($expressName == 1) {
            $arr['express_name'] = 'zhongtong';
        } elseif ($expressName == 2) {
            $arr['express_name'] = 'shunfeng';
        } else {
            $arr['express_name'] = 'yzdf';
        }
        if ($address == '上海' || $address == '浙江' || $address == '江苏') {
            $arr['express_price'] = $expressName == 2 ? 8 : 3;
        } else {
            $arr['express_price'] = $expressName == 2 ? 16 : 6;
        }
        return $arr;
    }

    /**
     * @var 检查商品
     */
    private function _checkGoods($goodsList, $userInfo)
    {
        $pidArray = array_column($goodsList, 'pid');
        $numArray = array_column($goodsList, 'num');
        $gidArray = array_column($goodsList, 'gid');
        if ($userInfo['userInfo']['is_vip'] != 1) {
            $find = 'pi.member_price as price';
        } else {
            $find = 'pi.price as price';
        }
        $price = 0;
        foreach ($pidArray as $k => $v) {
            $findPrice = Db::name('sy_product_info')->alias('pi')->where("pi.id = {$v} and pi.status = 1 and p.status = 1 and p.id = {$gidArray[$k]} and pi.stock > $numArray[$k]")
                ->join('sy_product p', 'p.id = pi.product_id')
                ->value($find);
            if (!$findPrice || (int)$numArray[$k] == 0) {
                return ('商品存在问题');
                break;
            } else {
                $goodsList[$k]['oprice'] = $findPrice;
                $price += ($findPrice * $numArray[$k]);
            }
        }
        return self::_createData($goodsList, $price, $userInfo['userInfo']['id']);
    }

    /**
     * @var 生成订单数据
     */
    static private function _createData($goodsList, $price, $id)
    {
        $orderNum = newOrderNum(1);
        $data['order']['order_num'] = $orderNum;
        $data['order']['uid'] = $id;
        $data['order']['ostate'] = 1;
        $data['order']['deal_price'] = $price;
        $data['info']['ouid'] = $id;
        $data['info']['goods'] = $goodsList;
        return $data;
    }

    /**
     * @var 检查优惠券
     */
    static private function _checkCoupon($coupon, $uid)
    {
        // 优惠券
        $couponPrice = 0;
        if ($coupon && count($coupon) <= 5) {
            $couponStr = implode(',', $coupon);
            $couponStatus = Db::name('sy_coupon')->where("id in(" . $couponStr . ") and uid = {$uid}")->field('price')->select();
            if (count($coupon) != count($coupon)) {
                return '你的优惠券存在异常';
            } else {
                $couponPrice = count($coupon) * 100;
            }
        } elseif ($coupon && count($coupon) > 5) {
            return '最多能使用5张优惠券';
        }
        $arr['couponPrice'] = $couponPrice;
        $arr['couponStr'] = empty($couponStr) ? '' : $couponStr;
        return $arr;
    }

    /**
     * @var 存储订单
     */
    private function _setOrder($orderInfo, $uid, $couponState, $express, $address)
    {
        $orderInfo['coupon'] = $couponState;
        $orderInfo['express'] = $express;
        $orderInfo['order']['oaddress'] = $address;
        $orderInfo['time'] = time();
        $redis = new Redis();
//        $cartArray = (new Cart())->deleteArr(array_column($orderInfo['info']['goods'], 'pid'), $id);
        $redis->hMset('lastOrder_' . $uid, ['order' => $orderInfo['order']['order_num'], 'time' => time()]);
        $redis->append('unpaid_' . $uid, $orderInfo['order']['order_num']);
        $redis->set($orderInfo['order']['order_num'], json_encode($orderInfo), 60 * 20);
    }

    /**
     * @var 检查用户身份和省份
     */
    private function _checkUser($uid, $address)
    {
        $province = Db::name('sy_address')->where("user_id = {$uid} and id = {$address}")->value('province');
        if (!$province) {
            return '您的收获地址不合法';
        }
        $userInfo = Db::name('sy_user')->where("id = {$uid} and status = 1")->field('id, openid, is_vip')->find();
        if (!$userInfo) {
            return '您的账号被封禁或者不存在';
        }
        $arr['userInfo'] = $userInfo;
        $arr['province'] = $province;
        return $arr;
    }

    private function _checkOrder($goodsList, $id)
    {
        $redis = new Redis();
        $lastOrder = $redis->hGetAll('lastOrder_' . $id);
        $pidArray = array_column($goodsList, 'pid');
        $numArray = array_column($goodsList, 'num');
        if ($lastOrder && time() - 60 * 15 < $lastOrder['time']) {
            $orderInfo = $redis->get($lastOrder['order']);
            if ($orderInfo) {
                $orderPid = array_column($orderInfo['info']['goods'], 'pid');
                $orderNum = array_column($orderInfo['info']['goods'], 'num');
                if (join(',', $orderPid) == join(',', $pidArray) && join(',', $numArray) == join(',', $orderNum)) {
                    return $orderInfo;
                }
            }
        }
        $gidArray = array_column($goodsList, 'gid');
        if ($gidArray) {
            $goodsStatus = count($gidArray) == count($pidArray) ? count($pidArray) == count($numArray) : false;
            if ($goodsStatus) {
                return true;
            }
        }
        return false;
    }


//    /**
//     * @var 返回微信支付价格
//     */
//    public function payOne()
//    {
//        $coupon = count(json_decode(input('post.coupon'), true)) ? json_decode(input('post.coupon'), true) : '';
//        $arr['oaddress'] = (int)input('post.address_id') ? (int)input('post.address_id') : 0;
//        $arr['uid'] = (int)session('Auth.Uid') ? (int)session('Auth.Uid') : 0;
//        $arr['express_name'] = (int)input('post.express') ? (int)input('post.express') : 0;
//        $goodsList = count(json_decode(input('post.goodslist'), true)) ? json_decode(input('post.goodslist'), true) : '';
//        if ($arr['uid'] && $arr['oaddress'] && $arr['express_name'] && $goodsList) {
//            $addressStatus = Db::name('sy_address')->where("user_id = {$arr['uid']} and id = {$arr['oaddress']}")->value('province');
//            if (!$addressStatus) {
//                return setMsg(0, '您的收获地址不合法');
//            }
//            $userStatus = Db::name('sy_user')->where("id = {$arr['uid']} and status = 1")->field('id, openid, is_vip')->find();
//            if (!$userStatus) {
//                return setMsg(0, '您的账号被封禁或者不存在');
//            }
//            if ($userStatus['is_vip'] == 1) {
//                $find = 'pi.member_price';
//            } else {
//                $find = 'pi.price';
//            }
//            $gidArray = array_column($goodsList, 'gid');
//            $pidArray = array_column($goodsList, 'pid');
//            $numArray = array_column($goodsList, 'num');
//            $price = 0;
//            $goodsStatus = count($gidArray) == count($pidArray) ? count($pidArray) == count($numArray) : false;
//            if (!$goodsStatus) {
//                return setMsg(0, '该订单有误');
//            }
//            foreach ($pidArray as $k => $v) {
//                $findPrice = Db::name('sy_product_info')->alias('pi')->where("pi.id = {$v} and pi.status = 1 and p.status = 1 and p.id = {$gidArray[$k]} and pi.stock > $numArray[$k]")
//                    ->join('sy_product p', 'p.id = pi.product_id')
//                    ->value($find);
//                if (!$findPrice || (int)$numArray[$k] == 0) {
//                    return ('商品存在问题');
//                    break;
//                } else {
//                    $goodsList[$k]['oprice'] = $findPrice;
//                    $price += ($findPrice * $numArray[$k]);
//                }
//            }
//            if ($arr['express_name'] > 2) {
//                return setMsg(0, '快递有问题');
//            }
//            // 快递价格计算
//            $data = $this->expressPrice(substr($addressStatus, 0, 3), $arr['express_name']);
//            // 优惠券
//            $couponPrice = 0;
//            if ($coupon && count($coupon) <= 5) {
//                $couponStr = implode(',', $coupon);
//                $couponStatus = Db::name('sy_coupon')->where("id in(" . $couponStr . ") and uid = {$arr['uid']}")->field('price')->select();
//                if (count($coupon) != count($coupon)) {
//                    return setMsg(0, '你的优惠券存在异常');
//                } else {
//                    $couponPrice = array_sum(array_column($couponStatus, 'price')) * 100;
//                }
//            } elseif ($coupon && count($coupon) > 5) {
//                return setMsg(0, '最多能使用5张优惠券');
//            }
//            $orderNum = newOrderNum(1);
//            $pay = new Pay();
//            $data['order']['order_num'] = $orderNum;
//            $data['order']['deal_price'] = $price - $couponPrice + $data['order']['express_price'];
//            $data['order']['uid'] = $arr['uid'];
//            $data['order']['ostate'] = 1;
//            $data['order']['oaddress'] = $arr['oaddress'];
//            $data['order']['coupon'] = $couponPrice;
//            $data['info']['ouid'] = $arr['uid'];;
//            $data['info']['goods'] = $goodsList;
//            $data['coupon'] = !empty($couponStr) ? $couponStr : '';
//            $result = $pay->getPreOrder($userStatus['openid'], $data['order']['deal_price'], $orderNum, 'call');
//            self::_setOrder($data, $goodsList, $orderNum, $arr['uid']);
////            (new Redis)->set($orderNum, json_encode($data), 60 * 20);
//            return $result;
//        } else {
//            return setMsg(0, '参数缺失');
//        }
//    }


//    /**
//     * @var 2个快递 2个地方
//     */
//    private function expressPrice($address, $expressName)
//    {
//
//    }


}
